package com.project.school_flate.serviceimpl.order;

import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.project.school_flate.service.com.WeiXinPayService;
import com.project.school_flate.util.wechat.PayDto;
import com.project.school_flate.util.wechat.WxMessagesManager;
import com.project.school_flate.dto.order.OrderTakeawayCancellationDto;
import com.project.school_flate.entity.order.OrderTakeaway;
import com.project.school_flate.entity.order.OrderTakeawayCancellation;
import com.project.school_flate.entity.order.OrderTakeawaySaveCache;
import com.project.school_flate.entity.order.table.OrderTakeawaySaveCacheTableDef;
import com.project.school_flate.entity.shop.ShopSaveUser;
import com.project.school_flate.entity.shop.table.ShopSaveUserTableDef;
import com.project.school_flate.entity.user.UserInfo;
import com.project.school_flate.mapper.flow.FlowBusinessMapper;
import com.project.school_flate.mapper.flow.FlowMoneyMapper;
import com.project.school_flate.mapper.order.OrderTakeawayCancellationMapper;
import com.project.school_flate.mapper.order.OrderTakeawayMapper;
import com.project.school_flate.mapper.order.OrderTakeawaySaveCacheMapper;
import com.project.school_flate.mapper.shop.ShopInfoMapper;
import com.project.school_flate.mapper.shop.ShopSaveUserMapper;
import com.project.school_flate.mapper.user.UserInfoMapper;
import com.project.school_flate.service.order.OrderTakeawayCancellationService;
import com.project.school_flate.util.PoToDTO;
import com.project.school_flate.util.Result.Result;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  服务层实现。
 *
 * @author 马维健
 * @since 2024/1/2
 */
@Service
public class OrderTakeawayCancellationServiceImpl extends ServiceImpl<OrderTakeawayCancellationMapper, OrderTakeawayCancellation> implements OrderTakeawayCancellationService {

    @Autowired
    private OrderTakeawayCancellationMapper oOrderTakeawayCancellationMapper;

    @Autowired
    private OrderTakeawayMapper oOrderTakeawayMapper;

    @Autowired
    private FlowBusinessMapper oFlowBusinessMapper;

    @Autowired
    private FlowMoneyMapper oFlowMoneyMapper;

    @Autowired
    private ShopSaveUserMapper oShopSaveUserMapper;

    @Autowired
    private OrderTakeawaySaveCacheMapper oOrderTakeawaySaveCacheMapper;

    @Autowired
    private UserInfoMapper oUserInfoMapper;

    @Autowired
    private WxMessagesManager wxMessagesManager;

    @Autowired
    private WeiXinPayService oWeiXinPayService;

    /**
     * 获取订单取消
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        List<OrderTakeawayCancellation> oOrderTakeawayCancellationList = new ArrayList<>();
        long total = 0;
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.orderBy("create_time desc");
        //是否分页
        if(oOrderTakeawayCancellationDto.getPage() != null && oOrderTakeawayCancellationDto.getLimit() != null){
            Page<OrderTakeawayCancellation> OrderTakeawayCancellationPage = oOrderTakeawayCancellationMapper.paginateWithRelations(oOrderTakeawayCancellationDto.getPage(),oOrderTakeawayCancellationDto.getLimit(),queryWrapper);
            oOrderTakeawayCancellationList = OrderTakeawayCancellationPage.getRecords();
            total = OrderTakeawayCancellationPage.getTotalRow();
        }else{
            oOrderTakeawayCancellationList = oOrderTakeawayCancellationMapper.selectListWithRelationsByQuery(queryWrapper);
            total = oOrderTakeawayCancellationList.size();
        }
        //PoToDto
        List<OrderTakeawayCancellationDto> oOrderTakeawayCancellationDtoList = (List<OrderTakeawayCancellationDto>) PoToDTO.poToDtoList(oOrderTakeawayCancellationList,new OrderTakeawayCancellationDto());
        return Result.ok(oOrderTakeawayCancellationDtoList,total);
    }

    /**
     * 添加订单取消
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result addOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        if(oOrderTakeawayCancellationMapper.insert(oOrderTakeawayCancellation) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("添加订单取消失败");
        }
        return Result.ok("添加订单取消成功");
    }

    /**
     * 修改订单取消
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result updateOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        if(oOrderTakeawayCancellationMapper.update(oOrderTakeawayCancellation) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("修改订单取消失败");
        }
        return Result.ok("修改订单取消成功");
    }

    /**
     * 删除订单取消
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result deleteOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        if(oOrderTakeawayCancellationMapper.deleteById(oOrderTakeawayCancellation.getId()) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("删除订单取消失败");
        }
        return Result.ok("删除订单取消成功");
    }

    /**
     * 店铺取消订单
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result shopOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        //获取订单信息
        OrderTakeaway oOrderTakeaway = oOrderTakeawayMapper.selectOneById(oOrderTakeawayCancellationDto.getOrderTakeawayId());
        if(oOrderTakeaway.getPayState() != 1){
            return Result.error("客户在对订单进行其他操作，无法取消订单");
        }
        if(oOrderTakeaway.getShopState() != 0){
            return Result.error("订单不是出餐中状态，无法取消订单");
        }
        if(oOrderTakeaway.getDeliveryState() != 0){
            return Result.error("配送员已接单，无法取消订单");
        }
        //如果是储蓄支付，返还储蓄余额
        if(oOrderTakeaway.getPaymentMethod() == 0){
            cancellationWXOrderTakeawayToUser(oOrderTakeaway);
        }else if(oOrderTakeaway.getPaymentMethod() == 1){
            cancellationSaveOrderTakeawayToUser(oOrderTakeaway);
        }else{

        }
        //修改订单
        oOrderTakeaway.setShopState(3);
        if(oOrderTakeawayMapper.update(oOrderTakeaway) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("店铺取消订单失败");
        }
        //添加取消记录
        oOrderTakeawayCancellation.setUserId(oOrderTakeaway.getUserId());
        oOrderTakeawayCancellation.setShopId(oOrderTakeaway.getShopId());
        oOrderTakeawayCancellation.setType(1);
        if(oOrderTakeawayCancellationMapper.insert(oOrderTakeawayCancellation) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("店铺取消订单失败");
        }
        return Result.ok();
    }

    /**
     * 取消微信支付订单
     * @param oOrderTakeaway
     * @return
     * @throws Exception
     */
    @Transactional
    public void cancellationWXOrderTakeawayToUser(OrderTakeaway oOrderTakeaway) throws Exception {
        PayDto payDto = new PayDto();
        payDto.setOutTradeNo(oOrderTakeaway.getId());
        payDto.setRefundsNotifyUrl("https://www.fanshanming.top/api/orderTakeawayCancellation/cancellationOrderTakeawayCallback");
        payDto.setRefundsRefund(oOrderTakeaway.getPrice());
        payDto.setRefundsTotal(oOrderTakeaway.getPrice());
        payDto.setRefundsUserId(oOrderTakeaway.getUserId());
        oWeiXinPayService.refundsPay(payDto);
    }

    /**
     * 取消微信支付订单（回调）
     * @param jsonObject
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> cancellationOrderTakeawayCallback(JSONObject jsonObject) throws Exception {
        System.out.println("---------------------------------------");
        System.out.println("退款通知：" + jsonObject);
        System.out.println("---------------------------------------");
        return null;
    }

    /**
     * 取消储蓄支付订单
     * @param oOrderTakeaway
     * @return
     * @throws Exception
     */
    @Transactional
    public void cancellationSaveOrderTakeawayToUser(OrderTakeaway oOrderTakeaway) throws Exception {
        //获取订单储蓄支付缓存
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(OrderTakeawaySaveCacheTableDef.ORDER_TAKEAWAY_SAVE_CACHE.ORDER_TAKEAWAY_ID.eq(oOrderTakeaway.getId()));
        List<OrderTakeawaySaveCache> oOrderTakeawaySaveCacheList = oOrderTakeawaySaveCacheMapper.selectListByQuery(queryWrapper);
        if(CollectionUtils.isNotEmpty(oOrderTakeawaySaveCacheList)){
            //获取查到的店铺用户储蓄ID集合
            List<String> oShopSaveUserIdList = new ArrayList<>();
            //重组订单储蓄支付缓存
            Map<String,Double> oOrderTakeawaySaveCacheMap = new HashMap<>();
            oOrderTakeawaySaveCacheList.forEach(item->{
                oShopSaveUserIdList.add(item.getShopSaveUserId());
                oOrderTakeawaySaveCacheMap.put(item.getShopSaveUserId(),item.getUserPrice());
            });
            //获取店铺用户储蓄
            queryWrapper = new QueryWrapper();
            queryWrapper.where(ShopSaveUserTableDef.SHOP_SAVE_USER.ID.in(oShopSaveUserIdList));
            List<ShopSaveUser> oShopSaveUserList = oShopSaveUserMapper.selectListByQuery(queryWrapper);
            //修改用户储蓄
            for(ShopSaveUser oShopSaveUser : oShopSaveUserList){
                UpdateChain.of(ShopSaveUser.class)
                        .setRaw(ShopSaveUser::getUserBalance, "balance + " + oOrderTakeawaySaveCacheMap.get(oShopSaveUser.getId()))
                        .set(ShopSaveUser::getIsSpend, 0)
                        .where(ShopSaveUser::getId).eq(oShopSaveUser.getId())
                        .update();
            }
            //删除订单储蓄支付缓存
            queryWrapper = new QueryWrapper();
            queryWrapper.where(OrderTakeawaySaveCacheTableDef.ORDER_TAKEAWAY_SAVE_CACHE.ORDER_TAKEAWAY_ID.eq(oOrderTakeaway.getId()));
            oOrderTakeawaySaveCacheMapper.deleteByQuery(queryWrapper);
        }
    }

    /**
     * 用户申请取消订单
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result userApplyOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        //获取订单信息
        OrderTakeaway oOrderTakeaway = oOrderTakeawayMapper.selectOneById(oOrderTakeawayCancellationDto.getOrderTakeawayId());
        if(oOrderTakeaway.getPayState() != 1){
            return Result.error("客户在对订单进行其他操作，无法取消订单");
        }
        if(oOrderTakeaway.getShopState() != 0){
            return Result.error("订单不是出餐中状态，无法取消订单");
        }
        if(oOrderTakeaway.getDeliveryState() != 0){
            return Result.error("配送员已接单，无法取消订单");
        }
        //修改订单
        oOrderTakeaway.setPayState(3);
        if(oOrderTakeawayMapper.update(oOrderTakeaway) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("用户申请取消订单失败");
        }
        //添加取消记录
        oOrderTakeawayCancellation.setUserId(oOrderTakeaway.getUserId());
        oOrderTakeawayCancellation.setShopId(oOrderTakeaway.getShopId());
        oOrderTakeawayCancellation.setType(0);
        if(oOrderTakeawayCancellationMapper.insert(oOrderTakeawayCancellation) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("用户申请取消订单失败");
        }
        return Result.ok();
    }

    /**
     * 平台确认取消订单
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result comOkOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        //获取订单信息
        OrderTakeaway oOrderTakeaway = oOrderTakeawayMapper.selectOneById(oOrderTakeawayCancellationDto.getOrderTakeawayId());
        //如果是储蓄支付，返还储蓄余额
        if(oOrderTakeaway.getPaymentMethod() == 0){
            cancellationWXOrderTakeawayToUser(oOrderTakeaway);
        }else if(oOrderTakeaway.getPaymentMethod() == 1){
            cancellationSaveOrderTakeawayToUser(oOrderTakeaway);
        }
        //修改订单状态
        oOrderTakeaway.setPayState(4);
        if(oOrderTakeawayMapper.update(oOrderTakeaway) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("确认取消订单失败");
        }
        //修改取消订单状态
        oOrderTakeawayCancellation.setState(1);
        if(oOrderTakeawayCancellationMapper.update(oOrderTakeawayCancellation) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("确认取消订单失败");
        }
        //获取用户信息
        UserInfo oUserInfo = oUserInfoMapper.selectOneById(oOrderTakeaway.getUserId());
        //推送消息
        Map<String,String> pushMap = new HashMap<>();
        pushMap.put("type","外卖订单");
        pushMap.put("oOrderTakeawayId",oOrderTakeaway.getId());
        pushMap.put("state","已取消");
        pushMap.put("content","您的订单已取消成功");
        wxMessagesManager.pushWxMessages(oUserInfo.getWxOptionId(),pushMap);
        return Result.ok();
    }

    /**
     * 平台驳回取消订单
     * @param oOrderTakeawayCancellationDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result comRejectOrderTakeawayCancellation(OrderTakeawayCancellationDto oOrderTakeawayCancellationDto) throws Exception {
        OrderTakeawayCancellation oOrderTakeawayCancellation = new OrderTakeawayCancellation();
        PoToDTO.poToDto(oOrderTakeawayCancellationDto,oOrderTakeawayCancellation);
        //获取订单信息
        OrderTakeaway oOrderTakeaway = oOrderTakeawayMapper.selectOneById(oOrderTakeawayCancellationDto.getOrderTakeawayId());
        //修改订单状态
        oOrderTakeaway.setPayState(1);
        if(oOrderTakeawayMapper.update(oOrderTakeaway) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("驳回取消订单失败");
        }
        //修改取消订单状态
        oOrderTakeawayCancellation.setState(2);
        if(oOrderTakeawayCancellationMapper.update(oOrderTakeawayCancellation) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("驳回取消订单失败");
        }
        //获取用户信息
        UserInfo oUserInfo = oUserInfoMapper.selectOneById(oOrderTakeaway.getUserId());
        //推送消息
        Map<String,String> pushMap = new HashMap<>();
        pushMap.put("type","外卖订单");
        pushMap.put("oOrderTakeawayId",oOrderTakeaway.getId());
        pushMap.put("state","取消失败");
        pushMap.put("content","您的订单取消失败，将继续配送");
        wxMessagesManager.pushWxMessages(oUserInfo.getWxOptionId(),pushMap);
        return Result.ok();
    }

}
